/*
 * Copyright Aristool AG Switzerland
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */
package org.opprua.tidy.gens;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.opprua.tidy.util.CodePrint;

/**
 * TODO: add Java doc
 * 
 * Prepared for first commit: 15.04.2007
 * 
 * @author Lin Li
 */
public class GMethod extends GState {

  private static class Parameter {

    public String type;
    public String name;

    public Parameter(String t, String n) {
      type = t;
      name = n;
    }
  }

  private String modifiers;
  private String returnType;
  private String name;
  private String exceptions;
  private List<Parameter> parameters;
  private boolean isAbstract = false;

  /**
   * <p>
   * Constructor for the method generator.
   * </p>
   * 
   * @param modifiers
   *          like <tt>"public static"</tt>, can be null or empty
   * @param name
   *          name of the method
   * @param returnType
   *          return type for the method
   */
  public GMethod(String modifiers, String name, String returnType) {
    this.modifiers = modifiers;
    this.returnType = returnType;
    this.name = name;
    parameters = new ArrayList<Parameter>();
  }

  /**
   * <p>
   * Sets the method to be static. If set, the method will be declared as such
   * and the body will be ignored.
   * </p>
   * 
   * @return this, for chained calls
   */
  public GMethod setIsAbstract() {
    this.isAbstract = true;
    return this;
  }

  /**
   * <p>
   * Sets the exception list by this method.
   * </p>
   * 
   * @param ex
   *          the exceptions
   */
  public GMethod setExceptions(String ex) {
    this.exceptions = ex;
    return this;
  }

  /**
   * <p>
   * Add a parameter to the method.
   * </p>
   * 
   * @param type
   *          type of the parameter
   * @param name
   *          name of the parameter
   * @return this, for chained calls
   */
  public GMethod addParameter(String type, String name) {
    this.parameters.add(new Parameter(type, name));
    return this;
  }

  /**
   * @see Gtor#dump(CodePrint w)
   */
  public void dump(CodePrint w) {

    javadoc(w);
    printAnnotation(w);

    w.print(test(modifiers) ? modifiers + " " : "");
    w.print(returnType);
    w.printPadded(name + "(");

    boolean first = true;
    for (Iterator<Parameter> i = parameters.iterator(); i.hasNext();) {
      Parameter p = (Parameter) i.next();
      if (!first) {
        w.print(", ");
        w.printPadded(p.type + " " + p.name);
      } else {
        first = false;
        w.print(p.type + " " + p.name);
      }
    }

    if (isAbstract) {
      w.println(");");
    } else {
      w.print(") ");
      if (exceptions != null && exceptions.trim().length() > 0) {
        w.print("throws ");
        w.print(exceptions);
        w.print(" ");
      }
      super.dump(w);
      w.println();
      w.println();
    }
  }
}
